package transport.netty.client;

import entity.RpcRequest;
import entity.RpcResponse;
import enumeration.RpcError;
import exception.RpcException;
import factory.SingleFacory;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import loadbalance.LoadBalance;
import loadbalance.RandomBalance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import register.NacosServiceDisCovery;
import register.ServiceDiscovery;
import serializer.Serializer;
import transport.RpcClient;

import java.net.InetSocketAddress;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class NettyClient implements RpcClient {
    private static final Logger logger = LoggerFactory.getLogger(NettyClient.class);


    private ServiceDiscovery serviceDiscovery;
    private Serializer serializer;
    private LoadBalance loadBalance;
    private final UnprocessedRequests unprocessedRequests;

    public NettyClient(Integer serializer) {
        this(serializer, new RandomBalance());
    }

    public NettyClient(Integer serializer, LoadBalance loadBalance) {
        this.serializer = Serializer.getBycode(serializer);
        this.loadBalance = loadBalance;
        this.serviceDiscovery = new NacosServiceDisCovery(loadBalance);
        this.unprocessedRequests = SingleFacory.getSingle(UnprocessedRequests.class);
    }

    @Override
    public CompletableFuture<RpcResponse> sendRequest(RpcRequest rpcRequest) {
        if (serializer == null) {
            logger.error("未设置序列化器");
            throw new RpcException(RpcError.SERIALIZER_NOT_FOUND);
        }
        //寻找对应的服务
        InetSocketAddress inetSocketAddress = serviceDiscovery.lookUPService(rpcRequest.getInterfaceName());
        //根据服务返回对应的 channel
        Channel channel = ChannelProvider.getChannel(inetSocketAddress, serializer);
        if (!channel.isActive()) {
            ChannelProvider.shutdownGracefully();
        }
        //发送数据 发送成功 返回一个结果
        channel.writeAndFlush(rpcRequest).addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                if (future.isSuccess()) {
                    logger.info("消息发送成功{}", rpcRequest.toString());
                }
            }
        });
        //使用异步编程 返回一个 结果
        CompletableFuture<RpcResponse> resultFuture = new CompletableFuture<>();
        unprocessedRequests.put(rpcRequest.getRequestId(), resultFuture);
        return resultFuture;
    }
}
/*
 * 需求：
 * 异步 获取 返回结果
 * 使用另外一个类暂存结果
 * 将 一个id, 结果绑定
 *
 * */